//
//  PageNavDropDelegate.swift
//  RssFly
//
//  Created by shen on 2023/10/17.
//

import CoreData
import SwiftUI
import UniformTypeIdentifiers

struct PageNavDropDelegate: DropDelegate {
    let context: NSManagedObjectContext
    let page: Page

    @Binding var newFeedPageID: String?
    @Binding var newFeedWebAddress: String
    @Binding var showingNewFeedSheet: Bool

    func performDrop(info: DropInfo) -> Bool {
        if info.hasItemsConforming(to: [.denFeed]) {
            for provider in info.itemProviders(for: [.denFeed]) {
                handleMoveFeed(provider)
            }

            return true
        }

        if info.hasItemsConforming(to: [.url, .text])
            && !info.hasItemsConforming(to: [.denItem, .denBookmark])
        {
            // Only recognize the first dropped item
            guard let provider = info.itemProviders(for: [.url, .text]).first else {
                return false
            }
            handleNewFeed(provider)

            return true
        }

        return false
    }

    private func handleMoveFeed(_ provider: NSItemProvider) {
        _ = provider.loadTransferable(type: TransferableFeed.self) { result in
            guard case let .success(transferableFeed) = result else { return }

            Task {
                await MainActor.run {
                    guard
                        let objectID = context.persistentStoreCoordinator?.managedObjectID(
                            forURIRepresentation: transferableFeed.objectURI
                        ),
                        let feed = try? context.existingObject(with: objectID) as? Feed,
                        feed.page != page
                    else { return }

                    feed.page = page
                    feed.userOrder = page.feedsUserOrderMax + 1

                    do {
                        try context.save()
                        page.objectWillChange.send()
                        page.profile?.objectWillChange.send()
                    } catch {
                        CrashUtility.handleCriticalError(error as NSError)
                    }
                }
            }
        }
    }

    private func handleNewFeed(_ provider: NSItemProvider) {
        if provider.canLoadObject(ofClass: URL.self) {
            _ = provider.loadObject(ofClass: URL.self, completionHandler: { url, _ in
                if let url = url {
                    newFeedPageID = page.id?.uuidString
                    newFeedWebAddress = url.absoluteStringForNewFeed
                    showingNewFeedSheet = true
                }
            })

            return
        }

        if provider.canLoadObject(ofClass: String.self) {
            _ = provider.loadObject(ofClass: String.self, completionHandler: { droppedString, _ in
                if let droppedString = droppedString {
                    newFeedPageID = page.id?.uuidString
                    newFeedWebAddress = droppedString
                    showingNewFeedSheet = true
                }
            })

            return
        }
    }
}
